import java.util.*;

class TreeNode{
    public char val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode(char val){
        this.val=val;
    }
}
 class BinaryTree {
     //相同的树
     public static boolean isSameTree(TreeNode p, TreeNode q) {
         //p和q都为空
         if (p == null && q == null) {
             return true;
         }//p和q一个为空
         if (p == null && q != null || p != null && q == null) {
             return false;
         }//p和q都不为空，但p和q的值不一样
         if (p.val != q.val) {
             return false;
         }
         return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
     }

     //另一颗的子树
     public static boolean isSubTree(TreeNode root, TreeNode subRoot) {
         //如果一个为空，直接返回false
         //这里不需要考虑两个为空的原因是：下面的if语句包含了两个为空的条件
         if (root == null || subRoot == null) {
             return false;
         }//先判断根结点和subRoot是不是一样的
         if (isSameTree(root, subRoot)) {
             return true;
         }//suRoot是不是root的左子树
         if (isSubTree(root.left, subRoot)) {
             return true;
         }//suRoot是不是root的右子树
         if (isSubTree(root.right, subRoot)) {
             return true;
         }//都不是返回false
         return false;
     }

     //树的最大深度
     public static int maxDepth(TreeNode root) {
         if (root == null) {
             return 0;//如果根节点为0返回0
         }
         //下一步根节点不为0 我们用递归的方法分别取找 左子树和右子树的高度
         int leftHeight = maxDepth(root.left);
         int rightHeight = maxDepth(root.right);
         //这里使用三目运算符 如果左子树的高度大于右子树那么就让左子树加1（加上根节点）
         return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
     }

     //判断是否是平衡二叉树
     public boolean isBalanced(TreeNode root) {
         if (root == null) {
             return true;
         }
         return getHeight(root) >= 0;
     }

     public int getHeight(TreeNode root) {
         if (root == null) {
             return 0;
         }
         int HeightLeft = getHeight(root.left);
         int HeightRight = getHeight(root.right);
         if (HeightLeft >= 0 && HeightRight >= 0 && Math.abs(HeightLeft - HeightRight) <= 1) {
             return Math.max(HeightLeft, HeightRight) + 1;
         } else {
             return -1;
         }
     }

     //是否是对称二叉树
     public boolean isSymmetric(TreeNode root) {
         if (root == null) {
             return true;
         }
         return isSymmetricChild(root.left, root.right);
     }

     public boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree) {
         if (leftTree == null && rightTree != null || leftTree != null && rightTree == null) {
             return false;
         }
         if (leftTree == null && rightTree == null) {
             return true;
         }
         if (leftTree.val != rightTree.val) {
             return false;
         }
         return isSymmetricChild(leftTree.left, rightTree.right) && isSymmetricChild(leftTree.right, rightTree.left);
     }


     //二叉树的层序遍历(二维数组)
     public List<List<Integer>> levelOrder(TreeNode root) {
         List<List<Integer>> ret = new ArrayList<>();
         if (root == null) {
             return ret;//如果root等于空，返回二维数组
         }
         Queue<TreeNode> queue = new LinkedList<>();//来存放元素
         queue.offer(root);//root入队列
         while (!queue.isEmpty()) {
             List<Integer> list = new ArrayList<>();//来存放弹出的元素，这样就可以分层了
             int size = queue.size();//代表当前层有多少个节点
             while (size != 0) {
                 TreeNode cur = queue.poll();
                 //这里注释的目的是因为，当前的树的元素类型是整型，而我们定义的是字符
                 //list.add(cur.val);//弹出的元素放入数组中
                 if (cur.left != null) {
                     queue.offer(cur.left);
                 }
                 if (cur.right != null) {
                     queue.offer(cur.right);
                 }
                 size--;
             }
             ret.add(list);//将分开的数组的放入二维数组中
         }
         return ret;
     }

     //二叉树的层序遍历
     public void levelOrder1(TreeNode root) {
         Queue<TreeNode> queue = new LinkedList<>();
         if (root == null) {
             return;
         }
         queue.offer(root);
         while (!queue.isEmpty()) {
             TreeNode cur = queue.poll();
             System.out.print(cur.val + " ");
             if (cur.left != null) {
                 queue.offer(cur.left);
             }
             if (cur.right != null) {
                 queue.offer(cur.right);
             }
         }
     }

     //二叉树的公共祖先
     public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
         if (root == null) {
             return null;
         }
         if (root == p || root == q) {//找到了p和q直接返回
             return root;
         }
         TreeNode left = lowestCommonAncestor(root.left, p, q);
         TreeNode right = lowestCommonAncestor(root.right, p, q);
         if (left != null && right != null) {//p和q在两边的情况
             return root;
         }
         if (left != null && right == null) {//p和q在左树的情况
             return left;
         }
         if (left == null && right != null) {//p和q在右树的情况
             return right;
         }
         return null;
     }


     public static void main(String[] args) {
         HashSet<String> set = new HashSet<>();
         Scanner scanner = new Scanner(System.in);
         while (scanner.hasNextLine()) {
             String str = scanner.nextLine();
             String[] strs = str.split(" ");
             for (String s : strs) {
                 set.add(s);
             }
         }
         System.out.print(set.size());
     }

     public static int func(int n) {
         int f1 = 0;
         int f2 = 1;
         int f3 = 0;
         while (f3 < n) {
             f3 = f1 + f2;
             if (f3 > n) {
                 break;
             }
             f1 = f2;
             f2 = f3;
         }
         if (n - f2 > f3 - n) {
             return f3 - n;
         } else {
             return n - f2;
         }
     }

     public static void main5(String[] args) {
         Scanner scanner = new Scanner(System.in);
         while (scanner.hasNextLine()) {
             int n = scanner.nextInt();
             int ret = func(n);
             System.out.println(ret);
         }
     }

     //求二叉树的公共祖先（用栈的方法）
     //找从根节点到指定 节点的路径，放入到栈中
     //root为根节点，node为目标节点，stack为存放从根节点到指定节点的路径
     public boolean getPath(TreeNode root, TreeNode node, Stack<TreeNode> stack) {
         if (root == null || node == null) {
             return false;
         }
         stack.push(root);//首先入根节点
         if (root == node) {//说明找到的目标节点
             return true;
         }
         boolean flag = getPath(root.left, node, stack);
         if (flag == true) {
             return true;
         }
         flag =getPath(root.right,node,stack);
             if(flag==true){
                 return true;
             }
             stack.pop();//如果左右其中一个没有找到就要弹出没有找到的节点
             return false;
         }

     public TreeNode lowestCommonAncestor3(TreeNode root,TreeNode p,TreeNode q){
         if(root==null){
             return null;
         }//存放p节点路径的栈
         Stack<TreeNode>stack1=new Stack<>();
         getPath(root,p,stack1);
         //存放q节点路径的栈
         Stack<TreeNode>stack2=new Stack<>();
         getPath(root,q,stack2);
         int size1=stack1.size();
         int size2=stack2.size();
         if(size1>size2){//判断两个栈的大小
             int size=size1-size2;//
             while(size!=0){
                 stack1.pop();
                 size--;
             }
             while(!stack1.isEmpty()&&!stack2.isEmpty()){
                 if(stack1.peek()==stack2.peek()){
                     return stack1.pop();
                 }
                 stack1.pop();
                 stack2.pop();
             }
         }
         else{
             int size=size2-size1;
             while(size!=0){
                 stack2.pop();
                 size--;
             }
             while(!stack1.isEmpty()&&!stack2.isEmpty()){
                 if(stack1.peek()==stack2.peek()){
                     return stack1.pop();
                 }
                 stack1.pop();
                 stack2.pop();
             }
         }
         return null;
     }



     //最后一块石头的重量
     public int lastStoneWeight(int []stones){
         Stack<Integer>stack=new Stack<>();
         Stack<Integer>stack1=new Stack<>();
         for(int stone:stones){
             stack.push(stone);
         }
         while(stack.size()>1){
             int newStone=stack.pop()-stack.pop();
             while(stack.size()>0&&stack.peek()>newStone){
                 stack1.push(stack.pop());
             }
             while(stack1.size()>0){
                 stack.push(stack1.pop());
             }
         }
         return stack.pop();
     }


     //给定100个数据，统计每个数据出现的次数
     public static void main4(String[] args) {
         int []array=new int [100];
         Random random=new Random();
         for(int i=0;i<array.length;i++){
             array[i]=random.nextInt(100);
         }
         Map<Integer,Integer>ret=func1(array);
         System.out.println(ret);
         //System.out.println(func2(array));
         System.out.println(func3(array));
     }
     public static Map<Integer,Integer>func1(int []array){
         HashMap<Integer,Integer>map=new HashMap<>();
         for(int x:array){
             if(map.get(x)==null){
                 map.put(x,1);
             }
             else{
                 int val=map.get(x);
                 map.put(x,val+1);
             }
         }
         return map;
     }

     //将100个数据去重
     public static Set<Integer>func2(int []array){
        HashSet<Integer>set=new HashSet<>();
        for(int x:array){
            set.add(x);
        }
        return set;
     }

     //将100个数据中，找到第一个重复的数据
     public static int func3(int []array){
        HashSet<Integer>set=new HashSet<>();
        for(int x:array){
            if(set.contains(x)){
                return x;
            }else{
                set.add(x);
            }
        }
        return -1;
     }


     //数组中找出只出现一次的数
     public int singleNumber1(int []nums){
        HashSet<Integer>set=new HashSet<>();
        for(int x:nums){
            if(set.contains(x)){
                set.remove(x);
            }
            else {
                set.add(x);
            }
        }
        for(int i=0;i<nums.length;i++){
            if(set.contains(nums[i])){
                return nums[i];
            }
        }
         return -1;
     }
     public static TreeNode createTree() {
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        return A;
    }

    //二叉树的遍历
     public static int i=0;
    public static TreeNode creatTree(String str){
        //因为构建的过程是递归的，不能用局部变量，要在外部设置为静态的
        if(str==null){//字符为空，直接返回
            return null;
        }
        TreeNode root=null;//创建一个根结点
        if(str.charAt(i)!='#'){//不是‘#’就进行构造
            root=new TreeNode(str.charAt(i));//将读取的字符节点实列化
            i++;
            root.left=creatTree(str);
            root.right=creatTree(str);
        }else{
            i++;//代表读取的是‘#’为空节点，不用构建，往后移
        }
        return root;
    }

//然后进行中序遍历
    public static void inOrderTree(TreeNode root){
        if(root==null){
            return ;
        }
        inOrderTree(root.left);
        System.out.print(root.val+" ");
        inOrderTree(root.right);
    }
//最后进行打印
     public static void main2(String[] args) {
         Scanner scanner=new Scanner(System.in);
         String str=scanner.nextLine();
         TreeNode root=creatTree(str);
         inOrderTree(root);
     }

    public static void main1(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
        TreeNode root = binaryTree.createTree();
        System.out.println(maxDepth(root));
    }
}

